package com.bestcem.xm.user.controller;

import cn.hutool.core.lang.ObjectId;
import com.bestcem.xm.common.core.domain.web.ServiceResult;
import com.bestcem.xm.common.core.uitls.DateUtil;
import com.bestcem.xm.common.core.uitls.IpUtil;
import com.bestcem.xm.common.core.uitls.TransactionUtils;
import com.bestcem.xm.component.security.annotation.AuthIgnore;
import com.bestcem.xm.user.dao.mapper.OrganizationMapper;
import com.bestcem.xm.user.dao.mapper.UnsubscribeSettingMapper;
import com.bestcem.xm.user.entity.mysql.Organization;
import com.bestcem.xm.user.entity.pojo.UnsubscribeSettingDO;
import com.bestcem.xm.user.enums.*;
import com.bestcem.xm.user.grpc.client.PackageGrpcService;
import com.bestcem.xm.user.grpc.client.dto.PackageDTO;
import com.bestcem.xm.user.mq.send.biz.UserMessageSendService;
import com.bestcem.xm.user.service.*;
import com.bestcem.xm.user.service.dto.role.UserRoleDTO;
import com.bestcem.xm.user.service.dto.user.OrganizationDTO;
import com.bestcem.xm.user.service.dto.user.UserDTO;
import com.bestcem.xm.user.util.UserAsyncUtil;
import com.bestcem.xm.user.util.business.DataBaseUtil;
import com.bestcem.xm.user.util.business.PwdUtil;
import com.bestcem.xm.user.util.business.UserUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * 脚本controller
 *
 * @author ympan <yuming.pan@idiaoyan.com>
 * @version v1.0
 * @date 2022/7/12 13:47
 */
@Slf4j
@RestController
@RequestMapping(value = "/user/script")
public class UserScriptController {
    @Resource
    private OrganizationMapper organizationMapper;

    @Resource
    private UnsubscribeSettingMapper unsubscribeSettingMapper;

    @Resource
    private HttpServletRequest request;

    /**
     * 初始化退订设置脚本
     *
     * @author ympan <yuming.pan@idiaoyan.com>
     * @date 16:50 2022/7/12
     */
    @AuthIgnore
    @GetMapping(value = "/unsubscribe_setting/init")
    public String initUnsubscribeSetting() {
        int limit = 1000;
        int offset = 0;
        Integer count = organizationMapper.count();
        if (Objects.isNull(count)) {
            log.error("【用户】初始化退订设置脚本失败 count为空, count:{}", count);
            return "failed";
        }
        while (true) {
            log.error("【用户】初始化退订设置脚本进度 count:{} limit:{} offset:{}", count, limit, offset);
            List<Organization> userOrganizations = organizationMapper.listByPaging(limit, offset);
            if (CollectionUtils.isEmpty(userOrganizations)) {
                break;
            }
            List<UnsubscribeSettingDO> list = new ArrayList<>(userOrganizations.size());
            for (Organization organization : userOrganizations) {
                // 根据orgId获取退订设置，如果非空则跳过（幂等）
                String orgId = organization.getOrgId();
                UnsubscribeSettingDO existingUnsubscribeSettingDO = unsubscribeSettingMapper.getByOrgId(orgId);
                if (Objects.nonNull(existingUnsubscribeSettingDO)) {
                    continue;
                }
                // 设置默认值
                UnsubscribeSettingDO unsubscribeSettingDO = new UnsubscribeSettingDO();
                unsubscribeSettingDO.setId(ObjectId.next());
                unsubscribeSettingDO.setOrgId(orgId);
                unsubscribeSettingDO.setType(UnsubscribeTypeEnum.PERMANENT.getType());
                unsubscribeSettingDO.setDuration(null);
                unsubscribeSettingDO.setCreatorId(null);
                unsubscribeSettingDO.setOperatorId(null);
                unsubscribeSettingDO.setCreateTime(DateUtil.getCommonDate());
                unsubscribeSettingDO.setUpdateTime(DateUtil.getCommonDate());
                list.add(unsubscribeSettingDO);
            }
            // 批量保存
            if (!CollectionUtils.isEmpty(list)) {
                unsubscribeSettingMapper.batchInsert(list);
            }
            offset += limit;
        }
        return "success";
    }

    private static final String LOCAL_HOST_IPV6 = "0:0:0:0:0:0:0:1";

    @Lazy
    @Resource
    private UserAsyncUtil userAsyncUtil;
    @Resource
    private UserOrgBusinessService userOrgBusinessService;
    @Resource
    private PackageGrpcService userPackageGrpcService;
    @Resource
    private OrganizationService organizationService;
    @Resource
    private UserPrivateKeyBusinessService userPrivateKeyBusinessService;
    @Resource
    private UserSmtpService userSmtpService;
    //@Resource
    //private OrganizationMessageSender organizationMessageSender;
    @Resource
    private UserMessageSendService userMessageSendService;
    @Resource
    private RoleService roleService;
    @Resource
    private UserUtil userUtil;
    @Resource
    private PlatformTransactionManager xmTransactionManager;
    @Resource
    private UserBusinessService userBusinessService;

    /**
     * 创建空白租户用脚本，主要用于创建新增的行业对应的sample租户
     *
     * @param phone 管理员手机号
     * @param email 管理员邮箱
     * @param code  租户代号
     * @author zhangfeng <feng.zhang@idiaoyan.com>
     * @date 2022/10/9 17:52
     */
    @AuthIgnore
    @GetMapping("/create_blank_company")
    public void createBlankCompany(@RequestParam(value = "phone", required = false, defaultValue = "15506183000") String phone,
                                   @RequestParam(value = "email", required = false, defaultValue = "xinxi.lou@idiaoyan.com") String email,
                                   @RequestParam(value = "code", required = false, defaultValue = "3c") String code) {
        String ip = IpUtil.getIpAddress(request);
        if (!LOCAL_HOST_IPV6.equals(ip)) {
            log.error("只允许本机执行");
        }
        log.error("创建开始 code:{} email:{} phone:{}", code, email, phone);
        String orgId = DataBaseUtil.generateId();
        String password = PwdUtil.genPassword();
        boolean successFlg = TransactionUtils.doTransaction(xmTransactionManager, () -> createCompany(orgId, password, phone, email, code));
        if (successFlg) {
            // 发送mq: 1.创建公司 2.创建免费公司
            userMessageSendService.userOrgCreate(orgId);
            //organizationMessageSender.userFreeOrgCreate(orgId);
            userAsyncUtil.notifyCompanyAcceptByEmail(orgId, password, null, null, phone);
        }
        log.error("创建结束");
    }

    private boolean createCompany(String orgId, String password, String phone, String email, String code) {
        String userId = DataBaseUtil.generateId();

        UserDTO userDTO = new UserDTO();
        userDTO.setUserId(userId);
        userDTO.setOrgId(orgId);
        userDTO.setName("超级管理员");
        userDTO.setUserName(phone);
        userDTO.setPhone(phone);
        userDTO.setEmail(email);
        userDTO.setAcceptFlag(UserAccpectFlagEnum.ACCPECT.getType());
        userDTO.setStatus(UserStatusEnum.ACTIVATED.getStatus());
        userDTO.setSalt(PwdUtil.genSalt());
        userDTO.setPassword(PwdUtil.getEncodePwd(password, userDTO.getSalt()));
        userDTO.setRegisterIp(StringUtils.EMPTY);
        userDTO.setWxNickname(StringUtils.EMPTY);
        userDTO.setWxOffiOpenid(StringUtils.EMPTY);
        userDTO.setWxUnionid(StringUtils.EMPTY);
        // 设置是否是内部员工
        if (StringUtils.isNotBlank(phone)) {
            boolean checkUserIsInner = userUtil.checkUserIsInner(phone, "", "");
            userDTO.setInnerFlag(checkUserIsInner ? UserInnerFlagEnum.INNER.getType() : UserInnerFlagEnum.OUTTER.getType());
        }

        OrganizationDTO organizationDTO = new OrganizationDTO();
        organizationDTO.setOrgId(orgId);
        organizationDTO.setCode(code);
        organizationDTO.setName("众言科技");
        organizationDTO.setAdminEmail(email);
        organizationDTO.setAdminPhone(phone);
        organizationDTO.setAdminName(phone);
        organizationDTO.setInnerFlag(userDTO.getInnerFlag());
        organizationDTO.setStatus(OrganizationStatusEnum.ACTIVATED.getStatus());
        organizationDTO.setSource(OrgSourceEnum.REGISTER.getType());

        // 获取类型为基础试用版的套餐信息
        PackageDTO freeTrialPackage = userPackageGrpcService.getByType(PackageTypeEnum.FREE_TRIAL.getType());
        if (freeTrialPackage == null) {
            log.error("获取免费版套餐失败");
            return false;
        }

        // 获取类型为基础版的套餐信息
        PackageDTO freePackage = userPackageGrpcService.getByType(PackageTypeEnum.FREE.getType());
        if (freePackage == null) {
            log.error("获取免费版套餐失败");
            return false;
        }
        userOrgBusinessService.setOrgPackageInfo(organizationDTO, freeTrialPackage, freePackage, DataBaseUtil.getDate());

        ServiceResult<String> createFreeOrgResult = this.createFreeOrg(organizationDTO);
        if (!createFreeOrgResult.isSuccess()) {
            log.error("创建机构失败");
            return false;
        }
        // 创建用户
        ServiceResult<String> createFreeUserResult = userOrgBusinessService.createFreeSystemUser(userDTO);
        if (!createFreeUserResult.isSuccess()) {
            log.error("创建用户失败");
            return false;
        }

        // 创建用户登录日志
        userBusinessService.updateUserLastLoginTime(userDTO, null);

        log.error("创建成功");
        return true;
    }

    private ServiceResult<String> createFreeOrg(OrganizationDTO organizationDTO) {
        // 校验公司code
        ServiceResult<String> checkOrgCodeRt = userOrgBusinessService.checkOrgCode(organizationDTO.getCode());
        if (!checkOrgCodeRt.isSuccess()) {
            return checkOrgCodeRt;
        }

        // 创建公司
        organizationDTO.setCheckSmtpId(DataBaseUtil.generateId());
        ServiceResult<String> orgCreateRt = organizationService.insert(organizationDTO);
        if (!orgCreateRt.isSuccess()) {
            return orgCreateRt;
        }
        // 创建系统管理员角色和对应的权限
        ServiceResult<UserRoleDTO> createAdminRoleRt = roleService.createAdminRole(organizationDTO);
        if (!createAdminRoleRt.isSuccess()) {
            return ServiceResult.fail(createAdminRoleRt.getMsg());
        }

        // 创建系统邮箱配置, 更新公司的系统邮箱配置
        userSmtpService.createSystemSmtp(organizationDTO.getOrgId(), organizationDTO.getCheckSmtpId());
        // 创建公司公私钥
        userPrivateKeyBusinessService.createOrgPrivateKeyInfo(organizationDTO.getOrgId());
        return ServiceResult.success();
    }
}